package com.example.testplatform.controller;

import com.example.testplatform.common.LogUtils;
import com.example.testplatform.common.Result;
import com.example.testplatform.entity.Menu;
import com.example.testplatform.service.MenuService;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Map;

/**
 * 菜单管理控制器
 * 提供菜单管理的CRUD操作
 */
@RestController
@RequestMapping("/api/system/menus")
public class MenuManageController {
    
    private static final Logger logger = LogUtils.getLogger(MenuManageController.class);
    
    @Autowired
    private MenuService menuService;
    
    /**
     * 获取菜单列表
     * @return 菜单列表
     */
    @GetMapping
    public Result<List<Menu>> getMenuList() {
        long startTime = System.currentTimeMillis();
        LogUtils.logBusiness(logger, "MENU_GET_LIST_ATTEMPT", "system", "获取菜单列表尝试");
        LogUtils.debug(logger, () -> "开始获取菜单列表");
        
        try {
            List<Menu> menus = menuService.getMenuList();
            LogUtils.info(logger, () -> "获取菜单列表成功，共 " + menus.size() + " 条记录");
            LogUtils.logBusiness(logger, "MENU_GET_LIST_SUCCESS", "system", "获取菜单列表成功，共 " + menus.size() + " 条记录");
            LogUtils.logPerformance(logger, "getMenuList", startTime, System.currentTimeMillis());
            return Result.success(menus);
        } catch (Exception e) {
            LogUtils.error(logger, "获取菜单列表失败: " + e.getMessage());
            LogUtils.logBusiness(logger, "MENU_GET_LIST_FAILED", "system", "获取菜单列表失败: " + LogUtils.formatException(e));
            LogUtils.logPerformance(logger, "getMenuList", startTime, System.currentTimeMillis());
            return Result.fail("获取菜单列表失败: " + e.getMessage());
        }
    }
    
    /**
     * 获取菜单详情
     * @param id 菜单ID
     * @return 菜单详情
     */
    @GetMapping("/{id}")
    public Result<Menu> getMenuById(@PathVariable Long id) {
        long startTime = System.currentTimeMillis();
        LogUtils.logBusiness(logger, "MENU_GET_DETAIL_ATTEMPT", "system", "获取菜单详情尝试: 菜单ID=" + id);
        LogUtils.debug(logger, () -> "开始获取菜单详情: 菜单ID=" + id);
        
        try {
            if (id == null || id <= 0) {
                LogUtils.warn(logger, "获取菜单详情失败: 参数校验失败，菜单ID={}", id);
                LogUtils.logBusiness(logger, "MENU_GET_DETAIL_FAILED", "system", "获取菜单详情失败: 参数校验失败，菜单ID=" + id);
                return Result.fail("菜单ID不能为空或无效");
            }
            
            Menu menu = menuService.getMenuById(id);
            if (menu != null) {
                LogUtils.info(logger, () -> "获取菜单详情成功: 菜单ID=" + id + ", 菜单名称=" + menu.getTitle());
                LogUtils.logBusiness(logger, "MENU_GET_DETAIL_SUCCESS", "system", "获取菜单详情成功: 菜单ID=" + id + ", 菜单名称=" + menu.getTitle());
                LogUtils.logPerformance(logger, "getMenuById", startTime, System.currentTimeMillis());
                return Result.success(menu);
            } else {
                LogUtils.warn(logger, "获取菜单详情失败: 菜单不存在，菜单ID={}", id);
                LogUtils.logBusiness(logger, "MENU_GET_DETAIL_FAILED", "system", "获取菜单详情失败: 菜单不存在，菜单ID=" + id);
                LogUtils.logPerformance(logger, "getMenuById", startTime, System.currentTimeMillis());
                return Result.fail("菜单不存在");
            }
        } catch (Exception e) {
            LogUtils.error(logger, "获取菜单详情失败: 菜单ID=" + id + ", 错误: " + e.getMessage());
            LogUtils.logBusiness(logger, "MENU_GET_DETAIL_FAILED", "system", "获取菜单详情失败: 菜单ID=" + id + ", 错误: " + LogUtils.formatException(e));
            LogUtils.logPerformance(logger, "getMenuById", startTime, System.currentTimeMillis());
            return Result.fail("获取菜单详情失败: " + e.getMessage());
        }
    }
    
    /**
     * 创建菜单
     * @param menu 菜单信息
     * @return 创建结果
     */
    @PostMapping
    public Result<String> createMenu(@RequestBody Menu menu) {
        long startTime = System.currentTimeMillis();
        LogUtils.logBusiness(logger, "MENU_CREATE_ATTEMPT", "system", "创建菜单尝试");
        LogUtils.debug(logger, () -> "开始创建菜单: " + (menu != null ? menu.toString() : "空菜单"));
        
        try {
            // 验证参数
            if (menu == null) {
                LogUtils.warn(logger, "创建菜单失败: 菜单信息为空");
                LogUtils.logBusiness(logger, "MENU_CREATE_FAILED", "system", "创建菜单失败: 菜单信息为空");
                return Result.fail("菜单信息不能为空");
            }
            
            if (menu.getMenuName() == null || menu.getMenuName().isEmpty()) {
                LogUtils.warn(logger, "创建菜单失败: 菜单名称不能为空");
                LogUtils.logBusiness(logger, "MENU_CREATE_FAILED", "system", "创建菜单失败: 菜单名称不能为空");
                return Result.fail("菜单名称不能为空");
            }
            
            LogUtils.debug(logger, () -> "参数校验通过，开始创建菜单: " + menu.getMenuName());
            boolean success = menuService.createMenu(menu);
            if (success) {
                LogUtils.info(logger, () -> "创建菜单成功: 菜单名称=" + menu.getMenuName() + ", 菜单ID=" + menu.getId());
                LogUtils.logBusiness(logger, "MENU_CREATE_SUCCESS", "system", "创建菜单成功: 菜单名称=" + menu.getMenuName() + ", 菜单ID=" + menu.getId());
                LogUtils.logPerformance(logger, "createMenu", startTime, System.currentTimeMillis());
                return Result.success("创建菜单成功");
            } else {
                LogUtils.warn(logger, "创建菜单失败: 菜单名称={}", menu.getMenuName());
                LogUtils.logBusiness(logger, "MENU_CREATE_FAILED", "system", "创建菜单失败: 菜单名称=" + menu.getMenuName());
                LogUtils.logPerformance(logger, "createMenu", startTime, System.currentTimeMillis());
                return Result.fail("创建菜单失败");
            }
        } catch (Exception e) {
            LogUtils.error(logger, "创建菜单失败: " + (menu != null ? menu.getMenuName() : "空菜单") + ", 错误: " + e.getMessage());
            LogUtils.logBusiness(logger, "MENU_CREATE_FAILED", "system", "创建菜单失败: " + (menu != null ? menu.getMenuName() : "空菜单") + ", 错误: " + LogUtils.formatException(e));
            LogUtils.logPerformance(logger, "createMenu", startTime, System.currentTimeMillis());
            return Result.fail("创建菜单失败: " + e.getMessage());
        }
    }
    
    /**
     * 更新菜单
     * @param id 菜单ID
     * @param menu 菜单信息
     * @return 更新结果
     */
    @PutMapping("/{id}")
    public Result<String> updateMenu(@PathVariable Long id, @RequestBody Menu menu) {
        long startTime = System.currentTimeMillis();
        LogUtils.logBusiness(logger, "MENU_UPDATE_ATTEMPT", "system", "更新菜单尝试: 菜单ID=" + id);
        LogUtils.debug(logger, () -> "开始更新菜单: 菜单ID=" + id + ", 菜单信息=" + (menu != null ? menu.toString() : "空菜单"));
        
        try {
            // 验证参数
            if (id == null || id <= 0) {
                LogUtils.warn(logger, "更新菜单失败: 菜单ID不能为空或无效");
                LogUtils.logBusiness(logger, "MENU_UPDATE_FAILED", "system", "更新菜单失败: 菜单ID不能为空或无效");
                return Result.fail("菜单ID不能为空或无效");
            }
            
            if (menu == null) {
                LogUtils.warn(logger, "更新菜单失败: 菜单信息为空");
                LogUtils.logBusiness(logger, "MENU_UPDATE_FAILED", "system", "更新菜单失败: 菜单信息为空");
                return Result.fail("菜单信息不能为空");
            }
            
            // 检查菜单是否存在
            Menu existingMenu = menuService.getMenuById(id);
            if (existingMenu == null) {
                LogUtils.warn(logger, "更新菜单失败: 菜单不存在，菜单ID={}", id);
                LogUtils.logBusiness(logger, "MENU_UPDATE_FAILED", "system", "更新菜单失败: 菜单不存在，菜单ID=" + id);
                return Result.fail("菜单不存在");
            }
            
            // 设置ID
            menu.setId(id);
            LogUtils.debug(logger, () -> "参数校验通过，开始更新菜单: 菜单ID=" + id + ", 菜单名称=" + menu.getMenuName());
            
            boolean success = menuService.updateMenu(menu);
            if (success) {
                LogUtils.info(logger, () -> "更新菜单成功: 菜单ID=" + id + ", 菜单名称=" + menu.getMenuName());
                LogUtils.logBusiness(logger, "MENU_UPDATE_SUCCESS", "system", "更新菜单成功: 菜单ID=" + id + ", 菜单名称=" + menu.getMenuName());
                LogUtils.logPerformance(logger, "updateMenu", startTime, System.currentTimeMillis());
                return Result.success("更新菜单成功");
            } else {
                LogUtils.warn(logger, "更新菜单失败: 菜单ID={}, 菜单名称={}", id, menu.getMenuName());
                LogUtils.logBusiness(logger, "MENU_UPDATE_FAILED", "system", "更新菜单失败: 菜单ID=" + id + ", 菜单名称=" + menu.getMenuName());
                LogUtils.logPerformance(logger, "updateMenu", startTime, System.currentTimeMillis());
                return Result.fail("更新菜单失败");
            }
        } catch (Exception e) {
            LogUtils.error(logger, "更新菜单失败: 菜单ID=" + id + ", 错误: " + e.getMessage());
            LogUtils.logBusiness(logger, "MENU_UPDATE_FAILED", "system", "更新菜单失败: 菜单ID=" + id + ", 错误: " + LogUtils.formatException(e));
            LogUtils.logPerformance(logger, "updateMenu", startTime, System.currentTimeMillis());
            return Result.fail("更新菜单失败: " + e.getMessage());
        }
    }
    
    /**
     * 删除菜单
     * @param id 菜单ID
     * @return 删除结果
     */
    @DeleteMapping("/{id}")
    public Result<String> deleteMenu(@PathVariable Long id) {
        long startTime = System.currentTimeMillis();
        LogUtils.logBusiness(logger, "MENU_DELETE_ATTEMPT", "system", "删除菜单尝试: 菜单ID=" + id);
        LogUtils.debug(logger, () -> "开始删除菜单: 菜单ID=" + id);
        
        try {
            // 验证参数
            if (id == null || id <= 0) {
                LogUtils.warn(logger, "删除菜单失败: 菜单ID不能为空或无效");
                LogUtils.logBusiness(logger, "MENU_DELETE_FAILED", "system", "删除菜单失败: 菜单ID不能为空或无效");
                return Result.fail("菜单ID不能为空或无效");
            }
            
            LogUtils.debug(logger, () -> "参数校验通过，开始执行删除操作: 菜单ID=" + id);
            boolean success = menuService.deleteMenu(id);
            if (success) {
                LogUtils.info(logger, () -> "删除菜单成功: 菜单ID=" + id);
                LogUtils.logBusiness(logger, "MENU_DELETE_SUCCESS", "system", "删除菜单成功: 菜单ID=" + id);
                LogUtils.logPerformance(logger, "deleteMenu", startTime, System.currentTimeMillis());
                return Result.success("删除菜单成功");
            } else {
                LogUtils.warn(logger, "删除菜单失败: 菜单ID={}, 可能存在子菜单", id);
                LogUtils.logBusiness(logger, "MENU_DELETE_FAILED", "system", "删除菜单失败: 菜单ID=" + id + ", 可能存在子菜单");
                LogUtils.logPerformance(logger, "deleteMenu", startTime, System.currentTimeMillis());
                return Result.fail("删除菜单失败，可能存在子菜单");
            }
        } catch (Exception e) {
            LogUtils.error(logger, "删除菜单失败: 菜单ID=" + id + ", 错误: " + e.getMessage());
            LogUtils.logBusiness(logger, "MENU_DELETE_FAILED", "system", "删除菜单失败: 菜单ID=" + id + ", 错误: " + LogUtils.formatException(e));
            LogUtils.logPerformance(logger, "deleteMenu", startTime, System.currentTimeMillis());
            return Result.fail("删除菜单失败: " + e.getMessage());
        }
    }
    
    /**
     * 更新菜单状态
     * @param id 菜单ID
     * @param params 状态参数
     * @return 更新结果
     */
    @PutMapping("/{id}/status")
    public Result<String> updateMenuStatus(@PathVariable Long id, @RequestBody Map<String, Integer> params) {
        long startTime = System.currentTimeMillis();
        LogUtils.logBusiness(logger, "MENU_UPDATE_STATUS_ATTEMPT", "system", "更新菜单状态尝试: 菜单ID=" + id);
        LogUtils.debug(logger, () -> "开始更新菜单状态: 菜单ID=" + id + ", 状态参数=" + params);
        
        try {
            // 验证参数
            if (id == null || id <= 0) {
                LogUtils.warn(logger, "更新菜单状态失败: 菜单ID不能为空或无效");
                LogUtils.logBusiness(logger, "MENU_UPDATE_STATUS_FAILED", "system", "更新菜单状态失败: 菜单ID不能为空或无效");
                return Result.fail("菜单ID不能为空或无效");
            }
            
            if (params == null || params.isEmpty()) {
                LogUtils.warn(logger, "更新菜单状态失败: 状态参数不能为空");
                LogUtils.logBusiness(logger, "MENU_UPDATE_STATUS_FAILED", "system", "更新菜单状态失败: 状态参数不能为空");
                return Result.fail("状态参数不能为空");
            }
            
            Integer status = params.get("status");
            if (status == null) {
                LogUtils.warn(logger, "更新菜单状态失败: 状态值不能为空");
                LogUtils.logBusiness(logger, "MENU_UPDATE_STATUS_FAILED", "system", "更新菜单状态失败: 状态值不能为空");
                return Result.fail("状态参数不能为空");
            }
            
            LogUtils.debug(logger, () -> "参数校验通过，开始更新菜单状态: 菜单ID=" + id + ", 目标状态=" + status);
            boolean success = menuService.updateMenuStatus(id, status);
            if (success) {
                LogUtils.info(logger, () -> "更新菜单状态成功: 菜单ID=" + id + ", 新状态=" + status);
                LogUtils.logBusiness(logger, "MENU_UPDATE_STATUS_SUCCESS", "system", "更新菜单状态成功: 菜单ID=" + id + ", 新状态=" + status);
                LogUtils.logPerformance(logger, "updateMenuStatus", startTime, System.currentTimeMillis());
                return Result.success("更新菜单状态成功");
            } else {
                LogUtils.warn(logger, "更新菜单状态失败: 菜单ID={}, 目标状态={}", id, status);
                LogUtils.logBusiness(logger, "MENU_UPDATE_STATUS_FAILED", "system", "更新菜单状态失败: 菜单ID=" + id + ", 目标状态=" + status);
                LogUtils.logPerformance(logger, "updateMenuStatus", startTime, System.currentTimeMillis());
                return Result.fail("更新菜单状态失败");
            }
        } catch (Exception e) {
            LogUtils.error(logger, "更新菜单状态失败: 菜单ID=" + id + ", 错误: " + e.getMessage());
            LogUtils.logBusiness(logger, "MENU_UPDATE_STATUS_FAILED", "system", "更新菜单状态失败: 菜单ID=" + id + ", 错误: " + LogUtils.formatException(e));
            LogUtils.logPerformance(logger, "updateMenuStatus", startTime, System.currentTimeMillis());
            return Result.fail("更新菜单状态失败: " + e.getMessage());
        }
    }
    
    /**
     * 获取菜单树结构
     * @return 菜单树
     */
    @GetMapping("/tree")
    public Result<List<Map<String, Object>>> getMenuTree() {
        long startTime = System.currentTimeMillis();
        LogUtils.logBusiness(logger, "MENU_GET_TREE_ATTEMPT", "system", "获取菜单树尝试");
        LogUtils.debug(logger, () -> "开始获取菜单树结构");
        
        try {
            List<Map<String, Object>> menuTree = menuService.getMenuTree(0L);
            LogUtils.info(logger, () -> "获取菜单树成功，共 " + menuTree.size() + " 个节点");
            LogUtils.logBusiness(logger, "MENU_GET_TREE_SUCCESS", "system", "获取菜单树成功，共 " + menuTree.size() + " 个节点");
            LogUtils.logPerformance(logger, "getMenuTree", startTime, System.currentTimeMillis());
            return Result.success(menuTree);
        } catch (Exception e) {
            LogUtils.error(logger, "获取菜单树失败: " + e.getMessage());
            LogUtils.logBusiness(logger, "MENU_GET_TREE_FAILED", "system", "获取菜单树失败: " + LogUtils.formatException(e));
            LogUtils.logPerformance(logger, "getMenuTree", startTime, System.currentTimeMillis());
            return Result.fail("获取菜单树失败: " + e.getMessage());
        }
    }
    
    /**
     * 根据角色ID获取菜单列表
     * @param roleId 角色ID
     * @return 菜单列表
     */
    @GetMapping("/by-role/{roleId}")
    public Result<List<Menu>> getMenusByRoleId(@PathVariable Long roleId) {
        long startTime = System.currentTimeMillis();
        LogUtils.logBusiness(logger, "MENU_GET_BY_ROLE_ATTEMPT", "system", "根据角色ID获取菜单列表尝试: 角色ID=" + roleId);
        LogUtils.debug(logger, () -> "开始根据角色ID获取菜单列表: 角色ID=" + roleId);
        
        try {
            // 验证参数
            if (roleId == null || roleId <= 0) {
                LogUtils.warn(logger, "根据角色ID获取菜单列表失败: 角色ID不能为空或无效");
                LogUtils.logBusiness(logger, "MENU_GET_BY_ROLE_FAILED", "system", "根据角色ID获取菜单列表失败: 角色ID不能为空或无效");
                return Result.fail("角色ID不能为空或无效");
            }
            
            LogUtils.debug(logger, () -> "参数校验通过，开始根据角色ID获取菜单列表: 角色ID=" + roleId);
            List<Menu> menus = menuService.getMenusByRoleId(roleId);
            LogUtils.info(logger, () -> "根据角色ID获取菜单列表成功: 角色ID=" + roleId + ", 菜单数量=" + menus.size());
            LogUtils.logBusiness(logger, "MENU_GET_BY_ROLE_SUCCESS", "system", "根据角色ID获取菜单列表成功: 角色ID=" + roleId + ", 菜单数量=" + menus.size());
            LogUtils.logPerformance(logger, "getMenusByRoleId", startTime, System.currentTimeMillis());
            return Result.success(menus);
        } catch (Exception e) {
            LogUtils.error(logger, "根据角色ID获取菜单列表失败: 角色ID=" + roleId + ", 错误: " + e.getMessage());
            LogUtils.logBusiness(logger, "MENU_GET_BY_ROLE_FAILED", "system", "根据角色ID获取菜单列表失败: 角色ID=" + roleId + ", 错误: " + LogUtils.formatException(e));
            LogUtils.logPerformance(logger, "getMenusByRoleId", startTime, System.currentTimeMillis());
            return Result.fail("获取角色菜单失败: " + e.getMessage());
        }
    }
}